#import "XApp.h"
#import "XMsg.h"
#import "UIView+X.h"

// XApp 单例对象
XApp   *g_App                 = nil;


@interface XApp() <UITabBarControllerDelegate, UINavigationControllerDelegate> {
    UINavigationController              *m_NavCtrl;
    
    UIImage                             *m_imgNavBack;
    UIImage                             *m_imgHighlightNavBack;
    CGFloat                             m_fOffset;
}

@end


@implementation XApp


/**
 * 添加通知响应
 * @param       target，响应通知的对象
 * @param       selector，对应的响应方法
 * @param       noti，对应的通知
 * @result
 */
+ (void)addTarget:(id)target sel:(SEL)selector forNotification:(NSString*)noti {
    [[NSNotificationCenter defaultCenter] addObserver:target
                                             selector:selector
                                                 name:noti
                                               object:nil];
}


+ (void)removeTarget:(id)target forNotification:(NSString*)noti {
    [[NSNotificationCenter defaultCenter] removeObserver:target name:noti object:nil];
}


#pragma mark 操作调用

/**
 * 创建XApp 单例对象
 * @result       XApp 对象
 */
+ (XApp *)si {
    @synchronized (self) {
        if (g_App == nil) {
            g_App = [[XApp alloc] init];
        }
    }
    
    return g_App;
}


/**
 * 获取应用版本
 * 获取应用当中 xxx-info.plist 文件中 Bundle version 字段对应的值
 * @result                           NSString类型，返回结果如：1.201
 */
+ (NSString*)appVersion {
    NSDictionary *infoDict =[[NSBundle mainBundle] infoDictionary];
    NSString *val =[infoDict objectForKey:(NSString *)kCFBundleVersionKey];
    return val;
}


/**
 * 设置 NavCtrl
 * @result
 */
- (void)setNavCtrl:(UINavigationController *)navCtrl {
    m_NavCtrl = navCtrl;
}


/**
 * 获取 NavCtrl
 * @result
 */
- (UINavigationController *)navCtrl {
    return m_NavCtrl;
}


/**
 * 设置返回按钮的正常图片
 * @param        image，返回按钮的正常图片
 * @result
 */
- (void)setNavBackImage:(UIImage *)image {
    m_imgNavBack = image;
}


/**
 * 设置返回按钮的高亮图片
 * @param        image，返回按钮的高亮图片
 * @result
 */
- (void)setNavBackHighlightImage:(UIImage *)image {
    m_imgHighlightNavBack = image;
}


/**
 * 设置返回按钮的水平偏移量
 * @param        offset，返回按钮的水平偏移量
 * @result
 */
- (void)setNavBackOffset:(CGFloat)offset {
    m_fOffset = offset;
}


/**
 * 操作调用
 *
 * cmd 规则如下：
 * 1、直接的网页跳转：http://www.wownew.cn
 * 2、应用跳转：ios:// + 视图控制器类名 + ?参数1=xx&参数2=xx……，如：ios://RouteDetailViewController?line_no=1
 *
 * 应用跳转界面响应编写规则：
 * 1、必须通过 initWithNibName:bundle: 初始化
 * 2、通过 setParams: 设置参数，参数通过 NSDictionary 进行封装
 * 3、通过 show 实现视图的导航加入（若没有show方法，则会直接调用 pushViewController 加入）
 *
 * @param   cmd     NSString 类型，命令
 * @result
 */
+ (void)excute:(NSString *)cmd {
    NSRange range = [cmd rangeOfString:@"ios://"];
    if (range.length > 0) {
        // 执行应用
        // 获取IOS对应的调用信息
        NSString *strCmd = [cmd substringFromIndex:range.location];
        range = [strCmd rangeOfString:@","];
        if (range.length > 0) {
            strCmd = [strCmd substringToIndex:range.location];
        }
        
        // 获取应用执行的视图控制器名称
        range = [strCmd rangeOfString:@"ios://"];
        NSString *strCtrl = [strCmd substringFromIndex:range.location + range.length];
        range = [strCtrl rangeOfString:@"?"];
        if (range.length > 0) {
            // 带参数
            NSString *strParams = [strCtrl substringFromIndex:range.location + range.length];
            // 类名
            strCtrl = [strCtrl substringToIndex:range.location];
            Class ctrlClass = NSClassFromString(strCtrl);
            if (nil != ctrlClass && [ctrlClass isSubclassOfClass:[UIViewController class]]) {
                UIViewController *vc = [[ctrlClass alloc] initWithNibName:strCtrl bundle:nil];
                if (vc) {
                    // 处理参数
                    NSArray *arrParams = [strParams componentsSeparatedByString:@"&"];
                    NSMutableDictionary *dicParams = [[NSMutableDictionary alloc] initWithCapacity:0];
                    for (NSString *strParam in arrParams) {
                        range = [strParam rangeOfString:@"="];
                        if (range.length>0) {
                            NSString *strKey = [strParam substringToIndex:range.location];
                            NSString *strValue = [strParam substringFromIndex:range.location+range.length];
                           [dicParams setValue:strValue forKey:strKey];
                        }
                    }
                    
                    // 设置参数
                    if ([vc respondsToSelector:@selector(setParams:)]) {
                        [vc performSelector:@selector(setParams:) withObject:dicParams];
                    }
                    
                    // 处理视图控制器
                    if ([vc respondsToSelector:@selector(show)]) {
                        [vc performSelector:@selector(show)];
                    }
                    else {
                        [XApp pushViewController:vc];
                    }
                }
            }
        }
        else {
            // 不带参数
            Class ctrlClass = NSClassFromString(strCtrl);   // 通过类名映射类
            if (nil != ctrlClass && [ctrlClass isSubclassOfClass:[UIViewController class]]) {
                UIViewController *vc = [[ctrlClass alloc] initWithNibName:strCtrl bundle:nil];      // 使用默认的初始化方法进行初始化
                if (vc) {
                    if ([vc respondsToSelector:@selector(show)]) {
                        [vc performSelector:@selector(show)];
                    }
                    else {
                        [XApp pushViewController:vc];
                    }
                }
            }
        }
    }
    else if ([cmd hasPrefix:@"http://"]) {
        // 直接的网页跳转
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:cmd]];
    }
}


/**
 * 打电话
 * @param   phone     NSString 类型，电话号码
 * @result
 */
+ (void)phoneCall:(NSString *)phone {
    if(nil == phone || phone.length == 0) {
        NSLog(@"参数错误！");
        return;
    }
    NSString *strURL = [NSString stringWithFormat:@"tel://%@", phone];
    if(![[UIApplication sharedApplication] openURL:[NSURL URLWithString:strURL]]){
        [XMsg showMessage:@"此设备不支持电话呼叫！" withTitle:@"呼叫电话失败"];
    }
}


/**
 * 判断当前设备是否为iPhone4、iTouch4
 * @result                           BOOL类型，是iPhone4或iTouch4设备时返回YES，否则返回NO
 */
+ (BOOL)isiDevice4 {
    return [UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(640, 960), [[UIScreen mainScreen] currentMode].size) : NO;
}


/**
 * 设置全局的返回按钮样式
 * @param   image，正常情况下的图片
 * @param   highlightImage，高亮时候的图片
 * @param   fOffSet，按钮便宜，若为负数，则按钮将往屏幕左边贴近，正数为远离屏幕左边
 * @result
 */
+ (void)setNavigationBackImage:(UIImage *)image
                highlightImage:(UIImage *)highlightImage
                        offSet:(CGFloat)fOffSet {
    XApp *pApp = [XApp si];
    [pApp setNavBackImage:image];
    [pApp setNavBackHighlightImage:highlightImage];
    [pApp setNavBackOffset:fOffSet];
}


#pragma mark 导航相关
/**
 * 设置根导航控制器
 * @param   rootNavigationController，根导航控制器
 * @result
 */
+ (void)setRootNavigationController:(UINavigationController *)rootNavgationController {
    XApp *pApp = [XApp si];
    pApp->m_NavCtrl = rootNavgationController;
    pApp->m_NavCtrl.delegate = pApp;
}


/**
 * 获取应用的 UINavigationController
 * @result                           UINavigationController 类型
 */
+ (UINavigationController *)rootNavgationController {
    XApp *pApp = [XApp si];
    return pApp->m_NavCtrl;
}

/**
 * 获取应用的 UINavigationController
 * @result                           UINavigationController 类型
 */
+ (UINavigationController *)navigationController {
    return [[XApp si] navCtrl];
}


/**
 * Push 入栈 将对应的视图控制器压入当前的导航栏视图控制器堆栈当中
 * @param   viewController          UIViewController 类型，需要压栈的视图控制器
 * @result
 */
+ (void)pushViewController:(UIViewController *)viewController {
    [XApp pushViewController:viewController withAnimate:YES];
}


/**
 * Push 入栈 将对应的视图控制器压入当前的导航栏视图控制器堆栈当中
 * @param   viewController          UIViewController 类型，需要压栈的视图控制器
 * @param   animate                 BOOL 类型，标识是否使用动画
 * @result
 */
+ (void)pushViewController:(UIViewController *)viewController withAnimate:(BOOL)animate {
    if (nil == viewController) {
        NSLog(@"错误的参数！");
        return;
    }
    
    UINavigationController *navCtrl = [[XApp si] navCtrl];
    if (nil == navCtrl) {
        NSLog(@"导航栏控制器获取异常！");
        return;
    }
    
    [viewController setHidesBottomBarWhenPushed:YES];
    [navCtrl pushViewController:viewController animated:animate];
}


/**
 * Pop 出栈 将最上方的视图控制器托出当前的导航栏视图控制器堆栈当中
 * @result
 */
+ (void)popViewController {
    [[[XApp si] navCtrl] popViewControllerAnimated:YES];
}


/**
 * Pop 出栈 将最上方的视图控制器托出当前的导航栏视图控制器堆栈当中
 * @param   animate                 BOOL 类型，标识是否使用动画
 * @result
 */
+ (void)popViewControllerWithAnimate:(BOOL)animate {
    [[[XApp si] navCtrl] popViewControllerAnimated:animate];
}


/**
 * Pop 出栈 退到指定的视图控制器
 * @param   viewController          UIViewController 类型，需要出栈的视图控制器位置（对应位置上的视图控制器）
 * @result
 */
+ (void)popViewControllerTo:(UIViewController *)viewController {
    if (nil == viewController) {
        NSLog(@"错误的参数！");
        return;
    }
    
    UINavigationController *navCtrl = [[XApp si] navCtrl];
    if (nil == navCtrl) {
        NSLog(@"导航栏控制器获取异常！");
        return;
    }
    
    [navCtrl popToViewController:viewController animated:YES];
}


/**
 * Pop 出栈 退到遇到指定的视图控制器类型
 * @param   viewControllerClass     Class 类型，需要出栈的视图控制器位置（Pop出视图控制器，直到遇到对应的视图控制器为止）
 * @result
 */
+ (void)popUntilMatchClassOfViewController:(Class)viewControllerClass {
    if (nil == viewControllerClass) {
        NSLog(@"错误的参数！");
        return;
    }
    
    UINavigationController *navCtrl = [[XApp si] navCtrl];
    if (nil == navCtrl) {
        NSLog(@"导航栏控制器获取异常！");
        return;
    }
    
    for (UIViewController *vc in navCtrl.viewControllers) {
        if ([vc isKindOfClass:viewControllerClass]) {
            [navCtrl popToViewController:vc animated:YES];
            break;
        }
    }
}


/**
 * Pop 出栈 退到拥有与指定的标题一致标题的视图控制器
 * @param   viewControllerTitle     NSString 类型，需要出栈的视图控制器位置（Pop出视图控制器，直到遇到对应的视图控制器标题为止）
 * @result
 */
+ (void)popUntilMatchTitleOfViewController:(NSString *)viewControllerTitle {
    if (nil == viewControllerTitle) {
        NSLog(@"错误的参数！");
        return;
    }
    
    UINavigationController *navCtrl = [[XApp si] navCtrl];
    if (nil == navCtrl) {
        NSLog(@"导航栏控制器获取异常！");
        return;
    }
    
    for (UIViewController *vc in navCtrl.viewControllers) {
        if ([vc.title isEqualToString:viewControllerTitle]) {
            [navCtrl popToViewController:vc animated:YES];
            break;
        }
    }
}


#pragma mark    UINavigationControllerDelegate
/**
 * 返回按钮响应方法
 * @result
 */
- (void)popViewController {
    [XApp popViewController];
}


- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    if (m_imgNavBack && navigationController.viewControllers.count > 1) {
        // 获取当前系统版本
        float fSysVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
        
        // 根据传入的图片，创建返回按钮
        UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, m_imgNavBack.size.width / 2, m_imgNavBack.size.height / 2)];
        [btn setImage:m_imgNavBack forState:UIControlStateNormal];
        if (m_imgHighlightNavBack) {
            [btn setImage:m_imgHighlightNavBack forState:UIControlStateHighlighted];
        }
        [btn addTarget:self action:@selector(popViewController) forControlEvents:UIControlEventTouchUpInside];
        UIBarButtonItem *btnNavBack = [[UIBarButtonItem alloc] initWithCustomView:btn];
        UIBarButtonItem *btnOffset = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
        btnOffset.width = fSysVersion >= 7.0f ? (m_fOffset - 10) : m_fOffset;
        NSArray *arrItems = [NSArray arrayWithObjects:btnOffset, btnNavBack, nil];
        
        viewController.navigationItem.leftBarButtonItems = arrItems;
    }
}


@end

